﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using FileSystem.Models;
using FileSystem.Services.IServices;
using SQLite;

namespace FileSystem.Services.Realization {
    /// <summary>
    /// 物理磁盘块存储
    /// </summary>
    public class PhysicalDiskBlockStorage : IPhysicalDiskBlockStorage {
        // ******** 公开变量
        /// <summary>
        /// PhysicalDiskBlockTable文件路径
        /// </summary>
        public static readonly string DbPath = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder
                .LocalApplicationData), DbName);

        /// <summary>
        /// PhysicalDiskBlockTable数据库连接
        /// </summary>
        private SQLiteAsyncConnection _connection;

        public SQLiteAsyncConnection Connection =>
            _connection ?? (_connection = new SQLiteAsyncConnection(DbPath));

        // ******** 私有变量
        /// <summary>
        /// TableDb文件名
        /// </summary>
        private const string DbName = "PhysicalDiskBlockTable.sqlite3";

        /// <summary>
        /// 偏好存储服务
        /// </summary>
        private IPreferenceStorage _preferenceStorage;

        // ******** 继承方法

        /// <summary>
        /// 初始化物理磁盘块存储
        /// </summary>
        public async Task InitializeAsync() {
            // PhysicalDiskBlockTable.sqlite3 文件初始化
            await Connection.CreateTableAsync<PhysicalDiskBlock>();

            // 将64个物理磁盘块写入物理磁盘块表中
            for (var i = 0; i < PhysicalDiskBlockConst.Count; i++) {
                var physicalDiskBlock = new PhysicalDiskBlock {Content = ""};
                await Connection.InsertAsync(physicalDiskBlock);
            }

            _preferenceStorage.Set(PhysicalDiskBlockStorageConstants.VersionKey,
                PhysicalDiskBlockStorageConstants.Version);
        }

        /// <summary>
        /// 物理磁盘块存储是否已经初始化
        /// </summary>
        public bool IsInitialized() {
            return _preferenceStorage.Get(
                    PhysicalDiskBlockStorageConstants.VersionKey,
                    PhysicalDiskBlockStorageConstants.DefaultVersion) ==
                PhysicalDiskBlockStorageConstants.Version;
        }

        /// <summary>
        /// 增加物理磁盘块
        /// </summary>
        /// <param name="physicalDiskBlock">要删除的物理磁盘块</param>
        public async Task AddAsync(PhysicalDiskBlock physicalDiskBlock) {
            await Connection.InsertAsync(physicalDiskBlock);
        }

        /// <summary>
        /// 删除物理磁盘块
        /// </summary>
        /// <param name="physicalDiskBlock">要删除的物理磁盘块</param>
        public async Task RemoveAsync(PhysicalDiskBlock physicalDiskBlock) {
            await Connection.DeleteAsync(physicalDiskBlock);
        }

        /// <summary>
        /// 修改物理磁盘块内容
        /// </summary>
        /// <param name="physicalBlockNumber">要修改的物理块块号</param>
        /// <param name="newContent">新内容</param>
        public async Task ModifyContent(int physicalBlockNumber,
            string newContent) {
            var physicalDiskBlock = await Connection.Table<PhysicalDiskBlock>()
                .FirstOrDefaultAsync(p =>
                    p.PhysicalBlockNumber == physicalBlockNumber);
            physicalDiskBlock.Content = newContent;

            await Connection.InsertOrReplaceAsync(physicalDiskBlock);
        }

        /// <summary>
        /// 根据物理块号获得一个物理磁盘块
        /// </summary>
        /// <param name="physicalBlockNumber">物理块号</param>
        public async Task<PhysicalDiskBlock> GetPhysicalDiskBlock(
            int physicalBlockNumber) {
            return await Connection.Table<PhysicalDiskBlock>()
                .FirstOrDefaultAsync(p =>
                    p.PhysicalBlockNumber == physicalBlockNumber);
        }

        /// <summary>
        /// 获得所有物理磁盘块
        /// </summary>]
        public async Task<IList<PhysicalDiskBlock>> GetPhysicalDiskBlocks() {
            return await Connection.Table<PhysicalDiskBlock>().ToListAsync();
        }

        /// <summary>
        /// 判断物理磁盘块是否存在
        /// </summary>
        /// <param name="physicalBlockNumber">物理块号</param>
        public async Task<bool> Exist(int physicalBlockNumber) {
            var item = await Connection.Table<PhysicalDiskBlock>()
                .FirstOrDefaultAsync(p =>
                    p.PhysicalBlockNumber == physicalBlockNumber);
            if (item == null)
                return false;
            else
                return true;
        }

        // ******** 公开方法

        /// <summary>
        /// 物理磁盘块存储
        /// </summary>
        public PhysicalDiskBlockStorage(IPreferenceStorage preferenceStorage) {
            _preferenceStorage = preferenceStorage;
        }

        /// <summary>
        /// 关闭数据库
        /// </summary>
        public async Task CloseAsync() {
            await Connection.CloseAsync();
        }

        // ******** 私有方法
    }
}